home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 6 / Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso / 031a / adg_1_3.zip / PMREST.C < prev    next >
C/C++ Source or Header  |  1991-02-21  |  10KB  |  321 lines

  1. /****************************************************************************
  2. Module name: PMRest.C
  3. Programmer : Jeffrey M. Richter.
  4. *****************************************************************************/
  5.  
  6. #include "..\nowindws.h"
  7. #undef NOCTLMGR
  8. #undef NOKERNEL
  9. #undef NOMB
  10. #undef NOMENUS
  11. #undef NOMSG
  12. #undef NOSHOWWINDOW
  13. #undef NOSYSCOMMANDS
  14. #undef NOUSER
  15. #undef NOWINOFFSETS
  16. #undef NOWINMESSAGES
  17. #include <windows.h>
  18.  
  19. #include "pmrest.h"
  20.  
  21.    // Menu IDs from Program Manager's menu.
  22. #define IDM_AUTO_ARRANGE         (0xC9)
  23. #define IDM_PMRESTOREABOUT       (4444)
  24. #define IDM_PMRESTOREREMOVE      (4445)
  25.  
  26. char _szAppName[] = "Program Manager Restore";
  27.  
  28.    // Class name of the Program Manager window.
  29. char _szPMClass[] = "PROGMAN";
  30.  
  31.    // Address for original window procedure.
  32. FARPROC _fpOrigPMProc = NULL;
  33.  
  34.    // Window handle of Program Manager.
  35. HWND _hWndPM = NULL;
  36.  
  37.    // Our instance handle.
  38. HANDLE _hInstance = NULL;
  39.  
  40.    // Our task handle.
  41. HANDLE _PMRestoreTask = NULL;
  42.  
  43.    // Forward reference to subclass function.
  44. LONG FAR PASCAL PMSubClass (HWND, WORD, WORD, LONG);
  45.  
  46.  
  47. int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpszCmdLine, int cmdShow) {
  48.    MSG msg;
  49.    DWORD dwWinFlags;
  50.    HMENU hMenu, hMenuPopup;
  51.    int nTopLevelMenuNum;
  52.  
  53.    dwWinFlags = GetWinFlags();
  54.    if ((dwWinFlags & WF_LARGEFRAME) || (dwWinFlags & WF_SMALLFRAME)) {
  55.       MessageBox(GetFocus(), "PM Restore cannot run with EMS memory.",
  56.          _szAppName, MB_OK | MB_SYSTEMMODAL);
  57.       return(FALSE);
  58.    }
  59.  
  60.    // Don't allow second instance of "PMRest" to run.
  61.    if (hPrevInstance != NULL) {
  62.       MessageBox(GetFocus(), "Application already running.",
  63.          _szAppName, MB_OK | MB_SYSTEMMODAL);
  64.       return(FALSE);
  65.    }
  66.  
  67.    // Get our data-instance handle and store it in a global variable.
  68.    _hInstance = hInstance;
  69.  
  70.    // Get our task-instance handle and store it in a global variable.
  71.    _PMRestoreTask = GetCurrentTask();
  72.  
  73.  
  74.    // Find window handle of Program Manager.
  75.    // Do not specify a caption because the Program Manager's caption
  76.    // changes depending whether a group is maximized or not.
  77.    _hWndPM = FindWindow(_szPMClass, NULL);
  78.  
  79.    if (_hWndPM == NULL) {
  80.  
  81.       // If the Program Manager's window couldn't be found, try to 
  82.       // execute the Program Manager application.
  83.       // This happens if PMREST.EXE is in the LOAD= line of the WIN.INI file.
  84.       WinExec("ProgMan", SW_SHOW);
  85.       _hWndPM = FindWindow(_szPMClass, NULL);
  86.  
  87.  
  88.       // If still can't find Program Manager, we can't subclass it and
  89.       // must terminate.
  90.       if (_hWndPM == NULL) {
  91.          MessageBox(GetFocus(), "Cannot find Program Manager.",
  92.             _szAppName, MB_OK);
  93.          return(FALSE);
  94.       }
  95.    }
  96.  
  97.  
  98.    // Get Menu handle to Program Manager's "Options" menu
  99.    hMenu = GetMenu(_hWndPM);
  100.  
  101.       // Get number of top level menu items
  102.    nTopLevelMenuNum = GetMenuItemCount(hMenu) - 1;
  103.    while (nTopLevelMenuNum) {
  104.  
  105.       // Get handle to popup menu.
  106.       hMenuPopup = GetSubMenu(hMenu, nTopLevelMenuNum);
  107.  
  108.  
  109.          // Is the first option in the popup menu IDM_AUTO_ARRANGE?
  110.       if (IDM_AUTO_ARRANGE == GetMenuItemID(hMenuPopup, 0)) {
  111.  
  112.          // Add a separator bar & "About PM Restore..." option to this menu
  113.          AppendMenu(hMenuPopup, MF_SEPARATOR, 0, 0);
  114.          AppendMenu(hMenuPopup, MF_ENABLED | MF_STRING,
  115.             IDM_PMRESTOREABOUT, "A&bout PM Restore...");
  116.          AppendMenu(hMenuPopup, MF_ENABLED | MF_STRING,
  117.             IDM_PMRESTOREREMOVE, "&Remove PM Restore");
  118.  
  119.          break;   // Stop check menus
  120.       }
  121.       nTopLevelMenuNum--;  // Try next menu
  122.    }
  123.  
  124.    DrawMenuBar(_hWndPM);      // Update the new menu bar
  125.  
  126.  
  127.    // Save present window function for the Program Manager in global variable
  128.    _fpOrigPMProc = (FARPROC) GetWindowLong(_hWndPM, GWL_WNDPROC);
  129.  
  130.  
  131.    // Set new window function for the Program Manager
  132.    SetWindowLong(_hWndPM, GWL_WNDPROC,
  133.       (LONG) MakeProcInstance((FARPROC) PMSubClass, hInstance));
  134.  
  135.  
  136.    // Running PMRest.EXE will minimize the Program Manager if 
  137.    // "Minimize on Use" is selected in the Program Manager's Options menu.
  138.    // Since there will not be an application switch, our subclassing will
  139.    // not restore the Program Manager automatically, so we must do it.
  140.    PostMessage(_hWndPM, WM_SYSCOMMAND, SC_RESTORE, 0);
  141.  
  142.  
  143.    // Begin message loop.  This is so that our application doesn't terminate.
  144.    // If we terminated, our subclass function would be removed from memory.
  145.    // When Windows tried to call it, it would jump to garbage.
  146.    while (GetMessage(&msg, NULL, 0, 0)) DispatchMessage(&msg);
  147.  
  148.    return(0);
  149. }
  150.  
  151.  
  152.  
  153.  
  154.    // Function to process About Box.
  155. BOOL FAR PASCAL AboutProc (HWND hDlg, WORD wMsg, WORD wParam, LONG lParam) {
  156.    char szBuffer[100];
  157.    BOOL fProcessed = TRUE;
  158.  
  159.    switch (wMsg) {
  160.  
  161.       case WM_INITDIALOG:
  162.          // Set version static window to have date and time of compilation.
  163.          wsprintf(szBuffer, "%s at %s", (LPSTR) __DATE__, (LPSTR) __TIME__);
  164.          SetWindowText(GetDlgItem(hDlg, ID_VERSION), szBuffer);
  165.          break;
  166.  
  167.       case WM_COMMAND:
  168.          switch (wParam) {
  169.             case IDOK: case IDCANCEL:
  170.                if (HIWORD(lParam) == BN_CLICKED)
  171.                   EndDialog(hDlg, wParam);
  172.                break;
  173.  
  174.             default:
  175.                break;
  176.          }
  177.          break;
  178.  
  179.       default:
  180.          fProcessed = FALSE; break;
  181.    }
  182.    return(fProcessed);
  183. }
  184.  
  185.  
  186.  
  187.  
  188.    // Forward reference to function called by EnumWindows.
  189. BOOL FAR PASCAL AnyAppsRunning (HWND, LONG);
  190.  
  191.  
  192.    // Subclass function for the Program Manager.  Any messages for the
  193.    // Program Manager window come here before reaching the original
  194.    // window function.
  195. LONG FAR PASCAL PMSubClass (HWND hWnd, WORD wMsg, WORD wParam, LONG lParam) {
  196.    FARPROC fpProc;
  197.    BOOL fAnyWindowsUp, fCallOrigProc = TRUE;
  198.    LONG lResult = 0L;
  199.    HMENU hMenu, hMenuPopup;
  200.    int nTopLevelMenuNum;
  201.  
  202.    switch (wMsg) {
  203.  
  204.    case WM_ACTIVATEAPP:
  205.       // Program Manager is either being activated or deactivated.
  206.  
  207.       if (wParam == 0) break;       // Program Manager is being deactivated.
  208.       if (!IsIconic(hWnd)) break;   // Program Manager isn't an icon.
  209.  
  210.       // Program Manager is being made active & is an icon.
  211.       // We have to check to see if any other applications are running.
  212.       fpProc = MakeProcInstance(AnyAppsRunning, _hInstance);
  213.       fAnyWindowsUp = (EnumWindows(fpProc, 0l) == 0);
  214.       FreeProcInstance(fpProc);
  215.  
  216.       // If the enumeration was stopped prematurely, there must be 
  217.       // at least one other application running.
  218.       if (fAnyWindowsUp) break;
  219.  
  220.       // No other applications are running, restore the Program Manager 
  221.       // to "open" state.
  222.       ShowWindow(hWnd, SW_RESTORE);
  223.       break;
  224.  
  225.    case WM_COMMAND:
  226.       switch (wParam) {
  227.  
  228.       case IDM_PMRESTOREABOUT:
  229.          // Our added menu option to display
  230.          // "About PM Restore..." was chosen.
  231.          fpProc = MakeProcInstance(AboutProc, _hInstance);
  232.          DialogBox(_hInstance, "About", hWnd, fpProc);
  233.          FreeProcInstance(fpProc);
  234.  
  235.          // Don't pass this message to Original Program Manager 
  236.          // window procedure because it wouldn't know what 
  237.          // to do with it.
  238.          fCallOrigProc = FALSE;
  239.          break;
  240.  
  241.       case IDM_PMRESTOREREMOVE:
  242.          // Stop window sub-classing by putting back the address of
  243.          // the original window procedure.
  244.          SetWindowLong(hWnd, GWL_WNDPROC, (LONG) _fpOrigPMProc);
  245.  
  246.  
  247.          // Get Menu handle to Program Manager's "Options" menu
  248.          hMenu = GetMenu(hWnd);
  249.          RemoveMenu(hMenu, IDM_PMRESTOREABOUT, MF_BYCOMMAND);
  250.          RemoveMenu(hMenu, IDM_PMRESTOREREMOVE, MF_BYCOMMAND);
  251.  
  252.             // Get number of top level menu items
  253.          nTopLevelMenuNum = GetMenuItemCount(hMenu) - 1;
  254.          while (nTopLevelMenuNum) {
  255.  
  256.             // Get handle to popup menu.
  257.             hMenuPopup = GetSubMenu(hMenu, nTopLevelMenuNum);
  258.  
  259.                // Is the first option in the popup menu IDM_AUTO_ARRANGE?
  260.             if (IDM_AUTO_ARRANGE == GetMenuItemID(hMenuPopup, 0)) {
  261.  
  262.                // Remove separator bar.
  263.                RemoveMenu(hMenuPopup, GetMenuItemCount(hMenuPopup) - 1,
  264.                   MF_BYPOSITION);
  265.  
  266.                break;   // Stop check menus
  267.             }
  268.             nTopLevelMenuNum--;  // Try next menu
  269.          }
  270.  
  271.          DrawMenuBar(hWnd);      // Update the new menu bar
  272.  
  273.  
  274.          // Post a WM_QUIT message to our application to remove it from
  275.          // memory.
  276.          PostAppMessage(_PMRestoreTask, WM_QUIT, 0, 0);
  277.          break;
  278.  
  279.       default: // Pass other WM_COMMAND's to original procedure
  280.          break;
  281.       }
  282.       break;
  283.  
  284.    default: // Pass other messages to original procedure
  285.       break;
  286.  
  287.    }
  288.  
  289.    if (fCallOrigProc) {
  290.       // Call original window procedure and return the result to whoever
  291.       // sent this message to the Program Manager.
  292.       lResult = CallWindowProc(_fpOrigPMProc, hWnd, wMsg, wParam, lParam);
  293.    }
  294.  
  295.    return(lResult);
  296. }
  297.  
  298.  
  299.  
  300.  
  301.    // Window's callback function to determine if any windows exist
  302.    // that should stop us from restoring the Program Manager
  303. BOOL FAR PASCAL AnyAppsRunning (HWND hWnd, LONG lParam) {
  304.    GetCurrentTask();
  305.  
  306.    // If window is the Window's desktop, continue enumeration
  307.    if (hWnd == GetDesktopWindow())
  308.       return(1);
  309.  
  310.    // If the window is invisible (hidden), continue enumeration
  311.    if (!IsWindowVisible(hWnd))
  312.       return(1);
  313.  
  314.    // If window is associated with the Program Manager, continue enumeration
  315.    if (GetWindowTask(_hWndPM) == GetWindowTask(hWnd))
  316.       return(1);
  317.  
  318.    // Any other type of window, stop enumeration
  319.    return(0);
  320. }
  321.